﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace Silverlight.Controls.ToolTips.Demo.Views
{
    public partial class ToolTipLifeTimeVisualizer
    {
        private double totalLifeTimeSeconds;
        private double pixelsPerSecond;
        private double rowHeight;
        private double actualWidth;
        private double actualHeight;

        private Rectangle delayRectangle;
        private Rectangle openAnimationRectangle;
        private Rectangle displayTimeRectangle;
        private Rectangle closeAnimationRectangle;

        private LinearGradientBrush redBrush;
        private LinearGradientBrush greenBrush;
        private LinearGradientBrush yellowBrush;
        private LinearGradientBrush orangeBrush;

        public ToolTipLifeTimeVisualizer()
        {
            InitializeComponent();
            InitializeBrushes();
        }

        private void InitializeBrushes()
        {
            OuterBorder.BorderBrush = CreateLinearGradientBrush(Colors.LightGray, new Point(0.5, 0), new Point(0.5, 1));
            LayoutRoot.Background = CreateLinearGradientBrush(Color.FromArgb(255, 75, 75, 75), new Point(0.5, 1), new Point(0.5, 0));
            redBrush = CreateLinearGradientBrush(Colors.Red);
            greenBrush = CreateLinearGradientBrush(Colors.Green);
            yellowBrush = CreateLinearGradientBrush(Colors.Yellow);
            orangeBrush = CreateLinearGradientBrush(Colors.Orange);
        }

        private static LinearGradientBrush CreateLinearGradientBrush(Color color)
        {
            return CreateLinearGradientBrush(color, new Point(0.25, 0.5), new Point(1, 0.5));
        }

        private static LinearGradientBrush CreateLinearGradientBrush(Color color, Point startPoint, Point endPoint)
        {
            var brush = new LinearGradientBrush();
            brush.StartPoint = startPoint;
            brush.EndPoint = endPoint;

            var endColor = new Color();
            endColor.A = color.A;
            endColor.R = color.R == 0 ? (byte)0 : (byte)(color.R / 3);
            endColor.G = color.G == 0 ? (byte)0 : (byte)(color.G / 3);
            endColor.B = color.B == 0 ? (byte)0 : (byte)(color.B / 3);

            brush.GradientStops.Add(new GradientStop { Color = color, Offset = 1 });
            brush.GradientStops.Add(new GradientStop { Color = endColor, Offset = -1.5 });

            return brush;
        }

        private Rectangle CreateRectangle(Brush brush, double width, Thickness margin)
        {
            var rectangle = new Rectangle();
            rectangle.Fill = brush;
            rectangle.VerticalAlignment = VerticalAlignment.Stretch;
            rectangle.StrokeThickness = 1;
            rectangle.Stroke = new SolidColorBrush(Color.FromArgb(255, 60, 60, 60));
            rectangle.Width = width;
            rectangle.Height = rowHeight;
            rectangle.HorizontalAlignment = HorizontalAlignment.Left;
            rectangle.Margin = margin;

            return rectangle;
        }

        public void StartVisualization(ToolTip toolTip)
        {
            if (actualWidth == 0)
                actualWidth = LayoutRoot.ActualWidth - 25;
            if (actualHeight == 0)
                actualHeight = LayoutRoot.ActualHeight;

            // calculate maximum seconds to display == 100% width of grid
            CalculateTotalLifeTimeSeconds(toolTip);
            if (totalLifeTimeSeconds <= 0) return;

            // add columndefinitions to the grid
            AddColumnDefinitions();

            // add rectangles
            AddDelayVisualization(toolTip);
            AddOpenAnimationVisualization(toolTip);
            AddDisplayTimeVisualization(toolTip);
            AddCloseAnimationRectangle(toolTip);
        }

        private void AddColumnDefinitions()
        {
            // clear child controls and columndefinitions collection
            LayoutRoot.Children.Clear();
            LayoutRoot.ColumnDefinitions.Clear();
            RectanglesLayoutRoot.Children.Clear();

            // for every whole second, add a columndefinition
            var lineHeight = actualHeight - 1;
            for (var i = 0; i < totalLifeTimeSeconds; i++)
            {
                var columnDefinition = new ColumnDefinition();
                columnDefinition.Width = new GridLength(pixelsPerSecond);

                var line = CreateLine(lineHeight);

                Grid.SetColumn(line, i);

                LayoutRoot.ColumnDefinitions.Add(columnDefinition);
                LayoutRoot.Children.Add(line);
            }
        }

        private Line CreateLine(double lineHeight)
        {
            var line = new Line();
            var strokeDashArray = new DoubleCollection { 4, 1, 2, 1 };

            line.StrokeThickness = 1;
            line.Stroke = new SolidColorBrush(Color.FromArgb(255, 200, 200, 200));
            line.StrokeDashArray = strokeDashArray;
            line.X1 = pixelsPerSecond - 1;
            line.X2 = pixelsPerSecond - 1;
            line.Y1 = 0;
            line.Y2 = lineHeight;

            return line;
        }

        private void AddCloseAnimationRectangle(ToolTip toolTip)
        {
            closeAnimationRectangle = null;

            if (!toolTip.DisplayTime.HasTimeSpan || toolTip.CloseAnimation == null || !toolTip.CloseAnimation.Duration.HasTimeSpan)
                return;

            var width = toolTip.CloseAnimation.Duration.TimeSpan.TotalSeconds * pixelsPerSecond;
            var margin = new Thickness(delayRectangle.Width + openAnimationRectangle.Width + displayTimeRectangle.Width - 1, 0, 0, 0);

            closeAnimationRectangle = CreateRectangle(redBrush, width, margin);

            RectanglesLayoutRoot.Children.Add(closeAnimationRectangle);
        }

        private void AddDisplayTimeVisualization(ToolTip toolTip)
        {
            displayTimeRectangle = null;

            var margin = new Thickness(delayRectangle.Width + openAnimationRectangle.Width, 0, 0, 0);
            var width = toolTip.DisplayTime.HasTimeSpan
                ? toolTip.DisplayTime.TimeSpan.TotalSeconds * pixelsPerSecond
                : actualWidth - margin.Left;

            displayTimeRectangle = CreateRectangle(yellowBrush, width, margin);

            RectanglesLayoutRoot.Children.Add(displayTimeRectangle);
        }

        private void AddOpenAnimationVisualization(ToolTip toolTip)
        {
            openAnimationRectangle = null;

            var width = toolTip.OpenAnimation.Duration.TimeSpan.TotalSeconds * pixelsPerSecond;
            var margin = new Thickness(delayRectangle.Width, 0, 0, 0);

            openAnimationRectangle = CreateRectangle(greenBrush, width, margin);

            RectanglesLayoutRoot.Children.Add(openAnimationRectangle);
        }

        private void AddDelayVisualization(ToolTip toolTip)
        {
            delayRectangle = null;

            var width = toolTip.InitialDelay.TimeSpan.TotalSeconds * pixelsPerSecond;
            var margin = new Thickness(0);

            delayRectangle = CreateRectangle(orangeBrush, width, margin);

            RectanglesLayoutRoot.Children.Add(delayRectangle);
        }

        private void CalculateTotalLifeTimeSeconds(ToolTip toolTip)
        {
            // reset calculation
            totalLifeTimeSeconds = 0;
            pixelsPerSecond = 0;
            rowHeight = actualHeight / 4;

            if (toolTip.InitialDelay.HasTimeSpan)
                totalLifeTimeSeconds += toolTip.InitialDelay.TimeSpan.TotalSeconds;

            if (toolTip.OpenAnimation.Duration.HasTimeSpan)
                totalLifeTimeSeconds += toolTip.OpenAnimation.Duration.TimeSpan.TotalSeconds;

            if (toolTip.DisplayTime.HasTimeSpan)
            {
                totalLifeTimeSeconds += toolTip.DisplayTime.TimeSpan.TotalSeconds;

                if (toolTip.CloseAnimation.Duration.HasTimeSpan)
                    totalLifeTimeSeconds += toolTip.CloseAnimation.Duration.TimeSpan.TotalSeconds;
            }
            else totalLifeTimeSeconds *= 3;

            pixelsPerSecond = actualWidth / totalLifeTimeSeconds;
        }
    }
}
